package disjunction.core
{
	import disjunction.core.Controller;
	import disjunction.core.IView;
	import disjunction.core.state.State;
	import disjunction.core.state.StateChangeEvent;
	import disjunction.core.timing.SimulationTimer;
	
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.utils.Timer;

	/**
	 * A state using MVC architecture, which can be configured in terms of each of the
	 * three aspects of the triad. Initiates the processing cycle for real-time controllers.
	 * 
	 * @author Nick Wiggill
	 */

	public class GameState extends State
	{
		private static const ERROR_CONFIG_REQD:String = "Parameter must be a GameStateConfiguration instance.";
		
		/** Generally the root context for the application */
		private var _controller:Controller = new Controller();
		
		//private var _entityManager:EntityManager;// = new EntityManager();
		
		/**
		 * @see disjunction.state.State
		 */
		public function GameState(id:String)
		{
			super(id);			
		}
		
		/** 
		 * Initialise the state. (AS3 does not allow overrides to change
		 * method overloading, so an inline type check is done here instead.)
		 * @param config The IController instance to use for initialisation.
		 */
		public override function initialise(config:Object):void
		{
			if (!(config is GameStateConfiguration))
				throw new ArgumentError(GameState.ERROR_CONFIG_REQD);

			var config_:GameStateConfiguration = config as GameStateConfiguration;
		
			_controller = config_.controller as Controller;
			_controller.timer = new SimulationTimer(0, 0, 0);
			
			//this call does not have access to the entities list yet (nor should it need it,
			//as it defines the model representing the entity lists)
			_controller.initialise(config_.data);
			
			//begin updates
			_controller.timer.addEventListener(TimerEvent.TIMER, update);
		
		}

		/** Should be called only by StateManager. Do not call manually. */
		//TODO: make internal? (some pitfalls? language-specific?)
		public override function deactivate():void
		{
			_controller.timer.removeEventListener(TimerEvent.TIMER, update);
			//super.deactivate(); //this currently does nothing.
		}
		
		private function changeState(e:StateChangeEvent):void
		{
			e.fromStateId = this.id;
			dispatchEvent(e); //should auto-call event.clone()
		}
		
		private function update(e:TimerEvent):void
		{
			while (_controller.timer.consumeInterval())
			{
				_controller.update(_controller.timer.updateIntervalMs);
			}
		}
	}
}